package com.bullsora.kindlerss.business;

import com.bullsora.kindlerss.model.Feed;
import com.bullsora.kindlerss.model.FeedUrl;
import com.bullsora.kindlerss.model.Subscription;
import com.bullsora.kindlerss.model.User;
import com.bullsora.kindlerss.repository.FeedRepository;
import com.bullsora.kindlerss.repository.GenericOperations;
import com.bullsora.kindlerss.repository.UserRepository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Date;
import java.util.Properties;

/**
 * @author sorin.buliarca@iquesint.com
 */
@SuppressWarnings({"unchecked"})
public class InitUsersService {

  private static final Log LOG = LogFactory.getLog(InitUsersService.class);

  private static final String USERS_PROPERTY_NAME = "accounts";
  private static final String SEPARATOR_IN_LIST = ",";
  private static final String ACCOUNT_SUBSCRIPTIONS_FORMAT = "account.%1$s.subscriptions";
  private static final String FEED_URL_FORMAT = "feed.%1$s.url";
  private static final String SUBSCRIPTIONS_CRON_EXPR_FORMAT = "subscription.%1$s.sendCronExpression";
  private static final String SUBSCRIPTIONS_FEEDS_FORMAT = "subscription.%1$s.feeds";
  public static final String USER_TIMEZONE_FORMAT = "account.%1$s.timezone";

  private GenericOperations genericOperations;

  private FeedRepository feedRepository;

  private UserRepository userRepository;

  public void initUsers(Properties properties) {
    String kindleAccountsProp = properties.getProperty(USERS_PROPERTY_NAME);

    if (kindleAccountsProp == null) {
      return;
    }

    String[] kindleAccounts = kindleAccountsProp.split(SEPARATOR_IN_LIST);
    for (String kindleAccount : kindleAccounts) {
      kindleAccount = kindleAccount.trim();

      User user = userRepository.findUserByKindleAccount(kindleAccount);
      if (user == null) {
        user = new User();
        genericOperations.persist(user);
      } else {
        deleteUserSubscriptions(user);
      }
      user.setKindleAccount(kindleAccount);
      user.setTimeZone(properties.getProperty(String.format(USER_TIMEZONE_FORMAT, kindleAccount)));
      processSubscriptions(properties, user);
      genericOperations.persist(user);
    }

  }

  private void deleteUserSubscriptions(User user) {
    genericOperations.delete(userRepository.getUserSubscriptions(user));
  }

  private void processSubscriptions(Properties properties, User user) {
    String subscriptionsProp = properties.getProperty(String.format(ACCOUNT_SUBSCRIPTIONS_FORMAT, user.getKindleAccount()));
    if (subscriptionsProp == null) {
      return;
    }

    String[] subscriptionPrefixes = subscriptionsProp.split(SEPARATOR_IN_LIST);
    for (String subscriptionPrefix : subscriptionPrefixes) {
      subscriptionPrefix = subscriptionPrefix.trim();
      addSubscription(properties, subscriptionPrefix, user);
    }
  }

  private void addSubscription(Properties props, String subscriptionPrefix, User user) {
    String feedsInSubscription = props.getProperty(String.format(SUBSCRIPTIONS_FEEDS_FORMAT, subscriptionPrefix));
    if (feedsInSubscription == null || feedsInSubscription.isEmpty()) {
      return;
    }

    LOG.info(String.format("User %1$s is subscribing to %2$s", user.getKindleAccount(), subscriptionPrefix));

    Subscription subscription = new Subscription();
    subscription.setUserId(user.getId());
    String sendCronExpression = props.getProperty(String.format(SUBSCRIPTIONS_CRON_EXPR_FORMAT, subscriptionPrefix));
    subscription.setPrefix(subscriptionPrefix);
    subscription.setSendCronExpression(sendCronExpression);
    subscription.setLastChecked(new Date());

    String[] feedNames = feedsInSubscription.split(SEPARATOR_IN_LIST);
    for (String feedName : feedNames) {
      feedName = feedName.trim();
      Feed feed = new Feed();
      feed.setShortName(feedName);
      String feedUrl = props.getProperty(String.format(FEED_URL_FORMAT, feedName));

      checkAddFeedUrl(feedUrl);

      feed.setUrl(feedUrl);
      subscription.getFeeds().add(feed);
    }
    genericOperations.persist(subscription);
  }

  private void checkAddFeedUrl(String url) {
    FeedUrl existingUrl = feedRepository.getFeedUrlByUrl(url);
    if (existingUrl == null) {
      FeedUrl feedUrl = new FeedUrl();
      feedUrl.setUrl(url);
      genericOperations.persist(feedUrl);
    }
  }

  public GenericOperations getGenericOperations() {
    return genericOperations;
  }

  public void setGenericOperations(GenericOperations genericOperations) {
    this.genericOperations = genericOperations;
  }

  public FeedRepository getFeedRepository() {
    return feedRepository;
  }

  public void setFeedRepository(FeedRepository feedRepository) {
    this.feedRepository = feedRepository;
  }

  public UserRepository getUserRepository() {
    return userRepository;
  }

  public void setUserRepository(UserRepository userRepository) {
    this.userRepository = userRepository;
  }
}
